package service

import (
	"IMChat/models"
	"IMChat/utils"
	"context"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
)

func Login(c *gin.Context) {
	account := c.PostForm("account")
	password := c.PostForm("password")
	if account == "" || password == "" {
		//c.JSON(http.StatusOK, gin.H{
		//	"code": -1,
		//	"msg":  "account and password can not be null",
		//})
		response := new(utils.Response)
		response.Code = -1
		utils.FailWithMsg(c, response.Code, "account and password can not be null")
		return
	}
	ub, err := models.GetUserBasicByAccountPassword(account, utils.Md5(password))
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "account or password is wrong",
		})
		return
	}
	token, err := utils.GenerateToken(ub.Identity, ub.Email)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "System wrong: " + err.Error(),
		})
		return
	}
	//c.JSON(http.StatusOK, gin.H{
	//	"code": http.StatusOK,
	//	"msg":  "login success",
	//	"data": gin.H{
	//		"token": token,
	//	},
	//})
	utils.OkWithData(c, gin.H{
		"token": token,
	})
}
func Register(c *gin.Context) {
	account := c.PostForm("account")
	email := c.PostForm("email")
	nickName := c.PostForm("nickname")
	password := c.PostForm("password")
	code := c.PostForm("code")
	//sex := c.PostForm("sex")

	if account == "" || email == "" || nickName == "" || password == "" || code == "" {
		res1 := new(utils.Response)
		res1.Code = -1
		utils.FailWithMsg(c, res1.Code, "FormData is wrong !")
		return
	}
	r, err := models.RDB.Get(context.Background(), "USER:CODE:"+email).Result()
	if err != nil {
		utils.FailWithMsg(c, -1, "code wrong !"+err.Error())
		return
	}
	if r != code {
		utils.FailWithMsg(c, -1, "code wrong !"+err.Error())
		return
	}
	count, err := models.Mongo.Collection(models.Userbasic{}.CollectionName()).
		CountDocuments(context.Background(), bson.D{{"account", account}})
	if err != nil {
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "Get User error :"+err.Error())

		return
	}
	if count > 0 {
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "Duplicate UserName")

		return
	}
	//Identity  string `bson:"_id"`
	//	Account   string `bson:"account"`
	//	Password  string `bson:"password"`
	//	Nickname  string `bson:"nickname"`
	//	Sex       int    `bson:"sex"`
	//	Email     string `bson:"email"`
	//	Avatar    string `bson:"avatar"`
	//	CreatedAt int64  `bson:"created_at"`
	//	UpdatedAt int64  `bson:"updated_at"`
	data := &models.Userbasic{
		Identity: utils.GetUUID(),
		Account:  account,
		Password: utils.Md5(password),
		Nickname: nickName,
		//Sex: sex,
		Email:     email,
		CreatedAt: time.Now().Unix(),
		UpdatedAt: time.Now().Unix(),
	}
	_, err = models.Mongo.Collection(models.Userbasic{}.CollectionName()).InsertOne(context.Background(), data)
	if err != nil {
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "Create User Error : "+err.Error())

		return
	}
	utils.OkWithMsg(c, "User register success !")
	return
}

func GetUserDetail(c *gin.Context) {
	u, _ := c.Get("user_claims")
	uc := u.(*utils.UserClaims)
	userBasic, err := models.GetUserBasicByIdentity(uc.Identity)
	if err != nil {
		log.Println("[DB ERROR]:%v\n", err)
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "database error")
		return
	}
	utils.OkWithData(c, userBasic)
	return
}

type UserProfileResult struct {
	Nickname string `bson:"nickname"`
	Sex      int    `bson:"sex"`
	Email    string `bson:"email"`
	Avatar   string `bson:"avatar"`
	IsFriend bool   `json:"is_friend"`
}

func GetUserBasicByAccount(account string) (*models.Userbasic, error) {
	ub := new(models.Userbasic)
	err := models.Mongo.Collection(models.Userbasic{}.CollectionName()).
		FindOne(context.Background(), bson.D{{"account", account}}).Decode(ub)
	if err != nil {
		return nil, err
	}
	return ub, nil
}
func UserProfile(c *gin.Context) {
	account := c.Query("account")
	if account == "" {
		utils.FailWithMsg(c, -1, "Param is wrong")
		return
	}
	userBasic, err := GetUserBasicByAccount(account)
	if err != nil {
		log.Printf("[DB ERROR]: " + err.Error())
		utils.FailWithMsg(c, -1, "Query Data Wrong !")
		return
	}
	uc := c.MustGet("user_claims").(*utils.UserClaims)

	data := &UserProfileResult{
		Nickname: userBasic.Nickname,
		Sex:      userBasic.Sex,
		Email:    userBasic.Email,
		Avatar:   userBasic.Avatar,
		IsFriend: false,
	}
	if models.JudgeUserIsFriend(userBasic.Identity, uc.Identity) {
		data.IsFriend = true
	}
	utils.OkWithData(c, data)
	return
}
func UserAdd(c *gin.Context) {
	account := c.Query("account")

	if account == "" {
		res1 := new(utils.Response)
		res1.Code = -1
		utils.FailWithMsg(c, res1.Code, "FormData is wrong !")
		return
	}
	cnt, err := GetUserBasicByAccount(account)
	if err != nil {
		log.Printf("[DB ERROR]: " + err.Error())
		utils.FailWithMsg(c, -1, "Query Data Wrong !")
		return
	}
	uc := c.MustGet("user_claims").(*utils.UserClaims)
	if models.JudgeUserIsFriend(uc.Identity, cnt.Identity) {
		utils.FailWithMsg(c, -1, "Duplicated Friend !")
		return
	}
	rb := &models.RoomBasic{
		Identity:     utils.GetUUID(),
		UserIdentity: uc.Identity,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}
	err = models.InsertOneRoomBasic(rb)
	if err != nil {
		log.Printf("[DB ERROR]: " + err.Error())
		utils.FailWithMsg(c, -1, "Insert RoomBasic Data Wrong !")
		return
	}
	ur := &models.UserRoom{
		UserIdentity: uc.Identity,
		RoomIdentity: rb.Identity,
		RoomType:     1,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}
	if err = models.InsertOneUserRoom(ur); err != nil {
		log.Printf("[DB ERROR]: " + err.Error())
		utils.FailWithMsg(c, -1, "Query Data Wrong !")
		return
	}
	ur = &models.UserRoom{
		UserIdentity: cnt.Identity,
		RoomIdentity: rb.Identity,
		RoomType:     1,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}
	if err = models.InsertOneUserRoom(ur); err != nil {
		log.Printf("[DB ERROR]: " + err.Error())
		utils.FailWithMsg(c, -1, "Query Data Wrong !")
		return
	}
	utils.OkWithMsg(c, "Add Friend Success !")

}
func UserDelete(c *gin.Context) {
	identity := c.Query("identity")
	if identity == "" {
		utils.FailWithMsg(c, -1, "identity can not be null")
		return
	}
	uc := c.MustGet("user_claims").(*utils.UserClaims)
	roomIdentity := models.GetUserRoomIdentity(identity, uc.Identity)
	if roomIdentity == "" {
		utils.FailWithMsg(c, -1, "room identity is null !")
		return
	}
	// 删除user_room关联关系
	if err := models.DeleteUserRoom(roomIdentity); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "系统异常",
		})
		return
	}
	// 删除room_basic
	if err := models.DeleteRoomBasic(roomIdentity); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "系统异常",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "删除成功",
	})
}
func SendCode(c *gin.Context) {
	email := c.PostForm("email")
	if email == "" {
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "email can not be null")
		return
	}
	cnt, err := models.GetUserBasicByEmail(email)
	if err != nil {
		log.Printf("[DB ERROR]: %v\n", err)
		return
	}
	if cnt > 0 {
		res2 := new(utils.Response)
		res2.Code = -1
		utils.FailWithMsg(c, res2.Code, "The email has been registered!")
		return
	}
	//err = utils.SendCode(email, utils.SendRandCode())
	//if err != nil {
	//	log.Printf("[ERROR]: %v\n", err)
	//	res2 := new(utils.Response)
	//	res2.Code = -1
	//	utils.FailWithMsg(c, res2, "Send Code Error")
	//	return
	//}
	code := utils.SendRandCode()
	log.Printf("[CODE]: %v\n", code)
	models.RDB.Set(context.Background(), "USER:CODE:"+email, code, 300*time.Second)
	utils.OkWithData(c, code)
	return
}
